import sys, os, logging, datetime
from pylons import config

log = logging.getLogger(__name__)

class LibPluginException(Exception):
	pass

class LibPluginInfo(object):
	def __init__(self, class_name, type_id, type_name, options, icon = None):
		self.type_id = type_id
		self.class_name = class_name
		self.type_name = type_name
		self.options = options
		self.icon = icon

class PluginOption(object):
	def __init__(self, opt_name, opt_desc, opt_type, variants):
		self.opt_name = opt_name
		self.opt_desc = opt_desc
		self.opt_type = opt_type
		self.variants = variants

class PluginsCache(object):
    """
    This is the BORG design pattern. It makes 
    all instances of this class share the same state
    by reinitializing its __dict__ with shared class member
    """    
    __shared_state = {}
    __meta = None
    
    def __init__(self):
        self.__dict__ = self.__shared_state
    
    def meta(self):
    	if not self.__meta:
        	self.__meta = []
        return self.__meta

def get_plugin_by_id(type_id):
	log.debug('***** Getting plugin by id: %s *****' % type_id)
	plugins = get_plugins()
	for p in plugins:
		if p.type_id == type_id:
			log.debug('***** Found *****')
			return p
	log.debug('***** Not Found. Failing... *****')
	raise LibPluginException('Plugin not found.')

def get_plugins(dirpath = 'enlargeweb/plugins'):
	plugins_meta = __get_cache().meta()
	#return value from cache
	if plugins_meta and len(plugins_meta) > 0:
		log.debug('***** Read %s Meta *****' % len(plugins_meta))
		return plugins_meta
	
	#reinit the cache 
	sys.path.insert( 1, dirpath )
	files = os.listdir(dirpath)
	files = filter(
		lambda x : x.endswith('.py'),
		files)
	
	for file in files:
		module = __import__(file[:-3], globals(), locals(), [], -1)

		for c in dir(module):
			if c.startswith('Plugin'):
				plugin_info = getattr(module, c).info
				plugins_meta.append(plugin_info)
				log.debug(' -- %s -- ' % file)
				log.debug('ID: %s' % plugin_info.type_id)
				log.debug('Plugin class: %s' % plugin_info.class_name)
				log.debug('Plugin type: %s' % plugin_info.type_name)
				log.debug('Options #: %s' % len(plugin_info.options))
				log.debug('Icon: %s' % plugin_info.icon)
	set_cache(plugins_meta)
	return get_cache()

def set_cache(plugins_meta):
	c = __get_cache()
	if not c:
		log.debug('***** Setting Plugins Cache *****')
		c.meta = plugins_meta
		log.debug('***** Total: %s *****' % len (c.meta))
		
def get_cache():
	c = __get_cache()
	if not c:
		log.debug('***** No Cache: Failing... *****')
		raise LibPluginException('Plugins cache is empty.')
	return c.meta()

def __get_cache():
	log.debug('***** Getting Plugins Cache *****')
	cache = PluginsCache()
	return cache


if __name__ == '__main__':
	get_plugins(sys.argv[1])

